#include "EdgeLinkedList.h"
#define NODE_DUMMY_INIT_VAL 0 // node list's head and tail dummy nodes are initialized with graph node data with this value

//////////////////////////////////////////////////////////////////////////////////// class EdgeLinkedList::EdgeInGraph's methods

//////////////////////////////////////////////////////////////////// public methods

/***************************************************************************************
* function name: EdgeInGraph(const Node& nodeOut, const Node& nodeIn)
* The Input: Two refernces to nodes to be linked by new edge
* The output: None
* The Function operation: Sets out-node and in-node pointers according to given origin
* 						  and destination, respectively. Given nodes are copied because
* 						  nodes are sent by value, hence pointing to local (static) values
* 						  will cause pointing at NULL as method ends
***************************************************************************************/
EdgeLinkedList::EdgeInGraph::EdgeInGraph(const Node& nodeOut, const Node& nodeIn): m_out(nodeOut), m_in(nodeIn) {
	// TODO DEBUG PRINT!!!
	cout << "in graph.edge constructor" << endl;
}

/***************************************************************************************
* function name: EdgeInGraph(const EdgeInGraph& edgeToCopy)
* The Input: Edge to be copied
* The output: None
* The Function operation: Sets new edge's node-pointer attributes as given edge's
***************************************************************************************/
EdgeLinkedList::EdgeInGraph::EdgeInGraph(const EdgeInGraph& edgeToCopy): m_out(edgeToCopy.m_out), m_in(edgeToCopy.m_in) { // TODO DEBUG!!! might be private to avoid copying an edge-in-graph by value
//Graph::EdgeInGraph::EdgeInGraph(const EdgeInGraph& edgeToCopy): m_out(*(new Node(edgeToCopy.m_out))), m_in(*(new Node(edgeToCopy.m_in))) {
	// TODO DEBUG PRINT!!!
	cout << "in graph.edge COPY constructor" << endl;
}

/***************************************************************************************
* function name: ~EdgeInGraph()
* The Input: None
* The output: None
* The Function operation: Destructs edge
***************************************************************************************/
EdgeLinkedList::EdgeInGraph::~EdgeInGraph() {
	// TODO DEBUG PRINT!!!
	cout << "in graph.edge destructor" << endl;
}

/***************************************************************************************
 * function name: == (const EdgeInGraph& operand) const
 * The Input: Edge operand to compare with
 * The output: True if given operand is equal to object
 * The Function operation: Uses Node object's comparison operator and compares both edges'
 * 						   node attributes
 ***************************************************************************************/
bool EdgeLinkedList::EdgeInGraph::operator == (const EdgeInGraph& operand) const {
	return (m_out == operand.m_out) && (m_in == operand.m_in);
}

/***************************************************************************************
 * function name: != (const EdgeInGraph& operand) const
 * The Input: Edge operand to compare with
 * The output: True if given operand is not equal to object
 * The Function operation: Returns negation of "==" operator between edges
 ***************************************************************************************/
bool EdgeLinkedList::EdgeInGraph::operator != (const EdgeInGraph& operand) const {
	return !(*this == operand);
}

/***************************************************************************************
 * function name: < (const EdgeInGraph& operand) const
 * The Input: Edge operand to compare with
 * The output: True if given operand's out and in nodes' values are bigger than object's
 * The Function operation: Uses Node object's comparison operator and compares both edges'
 * 						   node attributes
 ***************************************************************************************/
bool EdgeLinkedList::EdgeInGraph::operator < (const EdgeInGraph& operand) const {
	return (m_out < operand.m_out) && (m_in < operand.m_in);
}

/***************************************************************************************
 * function name: <= (const EdgeInGraph& operand) const
 * The Input: Edge operand to compare with
 * The output: True if both edges' out node value is equal and  given operand's in node
 * 			   value is bigger
 * The Function operation: Uses Node object's comparison operator and compares both edges'
 * 						   node attributes
 ***************************************************************************************/
bool EdgeLinkedList::EdgeInGraph::operator <= (const EdgeInGraph& operand) const {
	return (m_out == operand.m_out) && (m_in < operand.m_in);
}

/***************************************************************************************
 * function name: toString() const
 * The Input: None
 * The output: The string: "(out_Node_Value->in_Node_Value)"
 * The Function operation: Converts edge to a string
 ***************************************************************************************/
 const string EdgeLinkedList::EdgeInGraph::toString() const {
	return "(" + m_out.toString() + "->" + m_in.toString() + ")"; // create and return output string
 }

/***************************************************************************************
* function name: << (ostream &os, const EdgeInGraph& edgeToPrint)
* The Input: Reference to Edge to be printed
* The output: ostream reference
* The Function operation: TODO
***************************************************************************************/
ostream& operator << (ostream &os, const EdgeLinkedList::EdgeInGraph& edgeToPrint) {
	return os << "(" << int(edgeToPrint.m_out) << "->" << int(edgeToPrint.m_in) << ")";
}

//////////////////////////////////////////////////////////////////////////////////// class EdgeLinkedList::ListNode's methods

//////////////////////////////////////////////////////////////////// public methods

/***************************************************************************************
* function name: ListNode(EdgeInGraph& const edgeToPoint)
* The Input: Edge data to be set as data attribute
* The output: None
* The Function operation: Initializes edge data reference to given edge.
*						  Previous and next list node pointers are initialized as NULL and
*						  index is initialized as INDEX_INIT_VAL because the new list node's
*						  position in the linked list is not set yet
***************************************************************************************/
EdgeLinkedList::ListNode::ListNode(EdgeInGraph& edgeData): m_edgeData(edgeData) {

	// TODO DEBUG PRINT!!!
	cout << "in EdgeLinkedList.ListNode constructor" << endl;

	// new list node is not yet linked to the list
	m_prevListNode = NULL;
	m_nextListNode = NULL;
}

/***************************************************************************************
 * function name: Node(const ListNode& listNodeToCopy)
 * The Input: Node to be copied
 * The output: None
 * The Function operation: Creates a new list node whose attributes are set as given list
 * 						  node's
 ***************************************************************************************/
EdgeLinkedList::ListNode::ListNode(const ListNode& listNodeToCopy): m_edgeData( *(new EdgeInGraph(listNodeToCopy.m_edgeData)) ) {

	// TODO DEBUG PRINT!!!
	cout << "in EdgeLinkedList.ListNode COPY constructor" << endl;

	// set new list node's attributes as given node's
//	if (listNodeToCopy.m_edgeData != NULL){
//		m_edgeData = new EdgeInGraph(*listNodeToCopy.m_edgeData);
//	}

	// new list node is not yet linked to the list
	m_prevListNode = NULL;
	m_nextListNode = NULL;
}

/****************************************************************************************
* function name: ~ListNode()
* The Input: None
* The output: None
* The Function operation: Deletes edge data (but not the nodes that the edge data links).
* 				          Next and previous list nodes are linked and the next list nodes'
* 					      indices are decremented
***************************************************************************************/
EdgeLinkedList::ListNode::~ListNode() {

	// TODO DEBUG PRINT!!!
	cout << "in EdgeLinkedList.ListNode destructor" << endl;

	delete &m_edgeData; // // delete allocated memory for edge

	// link next node and previous node
	if (m_nextListNode != NULL) { // not end of list
		m_nextListNode->m_prevListNode = m_prevListNode;
	}
	if (m_prevListNode != NULL) { // not beginning of list
		m_prevListNode->m_nextListNode = m_nextListNode;
	}

//	// decrement next list nodes' index
//	ListNode* currListNode = m_nextListNode;
//	while (currListNode != NULL) { // scan list to its end
//		--(currListNode->m_index); // decrement index
//		currListNode = currListNode->m_nextListNode; // move to next node
//	}
}

//////////////////////////////////////////////////////////////////////////////////// class EdgeLinkedList's methods

//////////////////////////////////////////////////////////////////// private methods

/***************************************************************************************
* function name: findPlace(const EdgeInGraph& newEdge)
* The Input: Pointer to graph node to add
* The output: List node pointer to which the new graph node should be linked.
* 	          If a graph node with new graph node's number already exists, NULL is returned
* The Function operation: Uses 2 list node pointers- one to point at previous list node being
*			              scanned and another one to point at current node on list.
*	                      Method compares current graph node's number with given graph node's
*	                      number.
*			              If numbers are equal, given graph node cannot be added and NULL is
*			              returned. If current graph node's number is smaller than new graph
*			              node's, a pointer to current list node is returned
***************************************************************************************/
EdgeLinkedList::ListNode* EdgeLinkedList::findPlace(const EdgeInGraph& newEdge) const {

	ListNode* after = m_headDummy; // pointer to previous node being scanned
	ListNode* curr = after->m_nextListNode; // pointer to current node being scanned

	while (after->m_nextListNode != m_tailDummy) { // TODO check if works

		if (newEdge == curr->m_edgeData ) {
			return NULL; //duplicate edge found
		}

		// sort mainly by out-node
		// if new edge's out-node is smaller than current edge's on list, link before it
		if ( newEdge.getNodeOut() < curr->m_edgeData.getNodeOut() ) {
			return curr;
		}

//		if ( newEdge.getNodeOut() < curr->m_edgeData->getNodeOut() ) {
//			return curr;
//		}

		// sort secondarily by in-node
		/* if new edge's out-node is equal to current edge's on list, link before it only if
		 * new edge's in-node is smaller than current edge's */
		if (newEdge <= curr->m_edgeData) {
			return curr;
		}

		// move to next node on list
		after = curr;
		curr = curr->m_nextListNode;
	}

	return curr;
}

/***************************************************************************************
* function name: internalAdd(EdgeInGraph& edgeToAdd, Node* before)
* The Input: Reference to edge to be added and a pointer to the list node where the
* 			 new edge will be linked
* The output: None
* The Function operation: A new list node is created pointing to edge to be added.
*			              Method links the new list node before the given list node and
*			              then increments next list nodes' indices
***************************************************************************************/
void EdgeLinkedList::internalAdd(EdgeInGraph& edgeToAdd, ListNode* before) {

	ListNode* newListNode = new ListNode(edgeToAdd); // create a list node pointing to new edge
	// link list node to list
	ListNode* temp = before->m_prevListNode;
	newListNode->m_nextListNode = before;
	before->m_prevListNode = newListNode;

	newListNode->m_prevListNode = temp;
	temp->m_nextListNode = newListNode;

//	++(m_tailDummy->m_index); // increment tail's index
//	// update new list node's index
//	if (before == m_tailDummy) {
//		newListNode->m_index = m_tailDummy->m_index;
//	} else {
//		newListNode->m_index = before->m_index;
//	}
//	// increment index of next list nodes
//	while (before != m_tailDummy) {
//		before->m_index = (before->m_index)+1;
//		before = before->m_nextListNode;
//	}
}

//////////////////////////////////////////////////////////////////// public methods

/***************************************************************************************
* function name: EdgeLinkedList()
* The Input: None
* The output: None
* The Function operation: List's head and tail are pointers to list nodes which do not point
*			              at edges (point NULL). This implementation prevents the
*			              need to check if previous/next list nodes are NULL- makes code
*		                  more quick because there are less conditions to check
***************************************************************************************/
EdgeLinkedList::EdgeLinkedList() {

	// TODO DEBUG PRINT!!!
	cout << "in edge linked list constructor" << endl;

	// create dummy list nodes at list's begging and end to avoid checking NULL values

	/* create graph nodes to be set as head and tail's edge data
       the dummy graph nodes and edges will be deleted in head and tail's destructors */
	Node& headDataDummyOut = *(new Node(NODE_DUMMY_INIT_VAL)); // create dummy out-node
	Node& headDataDummyIn = *(new Node(NODE_DUMMY_INIT_VAL)); // create dummy in-node
	EdgeInGraph& headEdgeDummy = *(new EdgeInGraph(headDataDummyOut, headDataDummyIn)); // create dummy edge

	Node& tailDataDummyOut = *(new Node(NODE_DUMMY_INIT_VAL)); // create dummy out-node
	Node& tailDataDummyIn = *(new Node(NODE_DUMMY_INIT_VAL)); // create dummy in-node
	EdgeInGraph& tailEdgeDummy = *(new EdgeInGraph(tailDataDummyOut, tailDataDummyIn)); // create dummy edge

	// set dummy graph nodes as head and tail's data
	m_headDummy = new ListNode(headEdgeDummy);
	m_tailDummy = new ListNode(tailEdgeDummy);

	// link list's head and tail
	m_headDummy->m_nextListNode = m_tailDummy;
	m_tailDummy->m_prevListNode = m_headDummy;

	// TODO DEBUG!!!
	m_currNode = m_headDummy;
}

/***************************************************************************************
 * function name: EdgeLinkedList(const EdgeLinkedList& listToCopy)
 * The Input: List to be copied
 * The output: None
 * The Function operation: Creates an edge linked list whose node are copies of given
 * 						   list's nodes
 ***************************************************************************************/
EdgeLinkedList::EdgeLinkedList(const EdgeLinkedList& listToCopy) { // TODO might be private, edge lists will be copied via graph's copy Ctor

	// TODO DEBUG PRINT!!!
	cout << "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ in edge linked list COPY constructor" << endl;

	// set new list's attributes as given list's
	m_headDummy = new ListNode(*listToCopy.m_headDummy);
	m_tailDummy = new ListNode(*listToCopy.m_tailDummy);

	// TODO DEBUG!!! // keep
	// link head and tail
	m_headDummy->m_nextListNode = m_tailDummy;
	m_tailDummy->m_prevListNode = m_headDummy;

	// copy given list's nodes to new list

//	ListNode* prevListNode = m_headDummy; // list node pointer to previous node on new list
//	ListNode* currListNode = listToCopy.m_headDummy->m_nextListNode; // point to given list's first list node

	ListNode* currListNode = m_headDummy; // list node pointer to current node on new list
	ListNode* currOnGvnList = listToCopy.m_headDummy->m_nextListNode; // point to given list's first list node
	ListNode* currListNodeNextNodeBackp; // used to backup current node's on new list next node // TODO DEBUG!! check if works

	// scan given list to its end
//	while (currListNode->m_graphNodeData != NULL) {
//	while (currListNode != listToCopy.m_tailDummy) { // TODO check if works
	while (currOnGvnList != listToCopy.m_tailDummy) { // TODO check if works

		currListNodeNextNodeBackp = currListNode->m_nextListNode; // backup current node's on new list next node

		// TODO DEBUG!!!
//		Node& newEdgeOutNode = m_nodeList->searchByKey(currOnGvnList->m_edgeData.getNodeOut()); // reference to out node
//		Node& newEdgeInNode = *resultGraph.m_nodeList->searchByKey(edgeOpearand.getNodeIn()); // reference to in node
		/////

		currListNode->m_nextListNode = new ListNode(*currOnGvnList); // copy current node on given list
		// link new node to list
		currListNode->m_nextListNode->m_prevListNode = currListNode; // new node's previous node is current node on new list
		currListNode->m_nextListNode->m_nextListNode = currListNodeNextNodeBackp; // new node's next node is current node's on new list old next node
		currListNodeNextNodeBackp->m_prevListNode = currListNode->m_nextListNode; // current node's on new list old next node's previous node is new node

		currListNode = currListNode->m_nextListNode; // move to next node on new list
		currOnGvnList = currOnGvnList->m_nextListNode; // move to next node on given list

		// TODO previous implementation
//		prevListNode->m_nextListNode = new ListNode(*currListNode);
//		prevListNode->m_nextListNode->m_prevListNode = prevListNode;
//		currListNode = currListNode->m_nextListNode;

///////////////////////////////////////////////////////////////////////
//		// create a copy for each list node on given list
//		currListNode = new ListNode(*currListNode);
//
//		// link copy to new list
//		prevListNode->m_nextListNode = currListNode;
//		currListNode->m_prevListNode = prevListNode;
//
//		// move to next list node on given list
//		prevListNode = currListNode;
//		currListNode = currListNode->m_nextListNode;
	}

//	// set new list's attributes as given list's
//	m_headDummy = listToCopy.m_headDummy;
//	m_tailDummy = listToCopy.m_tailDummy;
//
//	// copy given list's nodes to new list
//	ListNode* prevListNode = m_headDummy; // list node pointer to previous node on new list
//	// list node pointer to current node on new list
//	ListNode* currListNode = listToCopy.m_headDummy->m_nextListNode; // point to given list's first list node
//
//	// scan given list to its end
////	while (currListNode->m_edgeData != NULL) { // TODO check if works
//	while (currListNode != m_tailDummy) {
//
//		// create a copy for each list node on given list
//		currListNode = new ListNode(*currListNode);
//
//		// link copy to new list
//		prevListNode->m_nextListNode = currListNode;
//		currListNode->m_prevListNode = prevListNode;
//
//		// move to next list node on given list
//		prevListNode = currListNode;
//		currListNode = currListNode->m_nextListNode;
//	}
}

/***************************************************************************************
 * function name: ~EdgeLinkedList()
 * The Input: None
 * The output: None
 * The Function operation: Scans list from start to end and deletes each node
 ***************************************************************************************/
EdgeLinkedList::~EdgeLinkedList() {

 	// TODO DEBUG PRINT!!!
 	cout << "in edge linked destructor" << endl;

 	// scan list and delete list nodes
 	ListNode* currNode = m_headDummy;
 	ListNode* prevNode = m_headDummy;

 	while (currNode != NULL) {
 		// move to next node on list and delete the previous which has been scanned
 		currNode = currNode->m_nextListNode;
 		delete prevNode;
 		prevNode = currNode;
 	}
 	delete prevNode; // delete last node on list
}

/***************************************************************************************
* function name: addNode(const EdgeInGraph& newEdge)
* The Input: Reference to edge to be added
* The output: True if graph was added, False is not
* The Function operation: Method calls findPlace to find where the new edge should
*			              be added. If no such place was found (returned value is NULL)
*		                  the method returns False. Otherwise, it calls internalAdd to
*			              add the new edge to the list and returns True
***************************************************************************************/
//bool EdgeLinkedList::addNode(const EdgeInGraph& newEdge) {
bool EdgeLinkedList::addNode(const Node& outNode, const Node& inNode) {

	const EdgeInGraph& newEdge = EdgeInGraph(outNode, inNode); // create an edge with given nodes
	ListNode* before = findPlace(newEdge); // find where, if any, edge can be added

	// check if duplicate id was found
	if (before == NULL) {
		return false;
	}

	EdgeInGraph* edgeToAdd = new EdgeInGraph(newEdge); // copy given edge and add copy to edge list
	internalAdd(*edgeToAdd, before); // add edge
	return true;
}

/***************************************************************************************
 * function name: removeListNode(const EdgeInGraph& edgeDataToRmv)
 * The Input: Reference to edge data whose list node should be removed
 * The output: True if removal was successful, False if not
 * The Function operation: Scans list and compares each list node's edge data with given
 * 						   value. If a match is found, current list node and edge data
 * 						   are deleted and True is returned. Otherwise, list is not changed
 * 						   and False is returned
 ***************************************************************************************/
bool EdgeLinkedList::removeListNode(const EdgeInGraph& edgeDataToRmv) {

	ListNode* currListNode = m_headDummy->m_nextListNode; // point to first list node
	// scan list and search for a list node that holds given data
	while (currListNode != NULL) {
		if (currListNode->m_edgeData == edgeDataToRmv) { // match found, remove current list node
			delete currListNode;
			return true;
		}
		currListNode = currListNode->m_nextListNode; // match not found, move to next node
	}
	return false; // if reached here match was not found
}

/***************************************************************************************
 * function name: <<
 * The Input: Reference to edge liked list to be printed
 * The output: ostream reference
 * The Function operation: Scans list and prints nodes, using Node object's ostream
 * 			               operator. Braces are also printed
 ***************************************************************************************/
ostream& operator << (ostream &os, const EdgeLinkedList& listToPrint) {
	// scan list and print each node
	cout << "|";
	EdgeLinkedList::ListNode* currListNode = listToPrint.m_headDummy->m_nextListNode; // point to first node on list

	if (currListNode == listToPrint.m_tailDummy) { // list is empty, done printing
		return os << "|";
	}

	// if reached here, list is not empty
	cout << currListNode->m_edgeData; // print first edge
	currListNode = currListNode->m_nextListNode; // move to next edge

	while (currListNode != listToPrint.m_tailDummy) { // scan list to its end
		cout << "," << currListNode->m_edgeData; // print current edge
		currListNode = currListNode->m_nextListNode; // move to next node on list
	}

	// done printing the list
	return os << "|";
}

/***************************************************************************************
 * function name: searchByKey(const EdgeInGraph& key)
 * The Input: Edge (in graph) to look for
 * The output: Pointer to edge that's equal to given key. If no such edge exists,
 * 			   NULL is returned.
 * The Function operation: Scans list- if a match is found, a pointer to this edge is
 * 						   returned. If not, NULL is returned.
 * 						   Method does not change list object
 ***************************************************************************************/
//const EdgeLinkedList::EdgeInGraph* EdgeLinkedList::searchByKey(const EdgeInGraph& key) const {
bool EdgeLinkedList::searchByKey(const EdgeInGraph& key) const {

	ListNode* currListNode = m_headDummy->m_nextListNode; // pointer to first list node in list

	// scan graph's node list to its end
	while (currListNode != m_tailDummy) {

		// check if current graph node on list is equal to given key
		if (currListNode->m_edgeData == key) {
			// if they are equal, return pointer to current edge
	//		return &(currListNode->m_edgeData);
			return true;
		}

		// move to next node
		currListNode = currListNode->m_nextListNode;

	} // while (currListNode != m_tailDummy)
	// if reached here, key was not found- return NULL
	//return NULL;
	return false;
}

/***************************************************************************************
 * function name: searchByKey(const Node& outNode, const Node inNode)
 * The Input: Out and in nodes of edge to look for
 * The output: Pointer to edge whose out and in node are equal to given keys. If no such
 * 			   edge exists, NULL is returned.
 * The Function operation: Scans list- if a match is found, a pointer to this edge is
 * 						   returned. If not, NULL is returned.
 * 						   Method does not change list object
 ***************************************************************************************/
bool EdgeLinkedList::searchByKey(const Node& outNode, const Node& inNode) const {

	ListNode* currListNode = m_headDummy->m_nextListNode; // pointer to first list node in list

	// scan graph's node list to its end
	while (currListNode != m_tailDummy) {

		// check if current graph node on list is equal to given key
		if (currListNode->m_edgeData.getNodeOut() == outNode && currListNode->m_edgeData.getNodeIn() == inNode) {
			// if they are equal, return pointer to current edge
			//return &(currListNode->m_edgeData);
			return true;
		}

		// move to next node
		currListNode = currListNode->m_nextListNode;

	} // while (currListNode != m_tailDummy)
	// if reached here, key was not found- return NULL
//	return NULL;
	return false;

}

/***************************************************************************************
 * function name: removeEdges(const Node& nodeToRmv)
 * The Input: Reference to graph node that edges that link it should be removed
 * The output: None
 * The Function operation: Removes all edges that have given graph node as out/in node
 ***************************************************************************************/
void EdgeLinkedList::removeEdges(const Node& nodeToRmv) {
	ListNode* currListNode = m_headDummy->m_nextListNode; // pointer to first list node in list
	// scan graph's node list to its end
	while (currListNode != m_tailDummy) {
		if (currListNode->m_edgeData.getNodeOut() == nodeToRmv || currListNode->m_edgeData.getNodeIn() == nodeToRmv) {
			delete currListNode; // match found, delete list node
		}
		currListNode = currListNode->m_nextListNode; // move to next node on list
	}
}

/***************************************************************************************
 * function name: incrmntCurrNode()
 * The Input: None
 * The output: False if reached list's tail dummy node or if a next list node does
 * 			   not exist. Otherwise, returns true
 * The Function operation: Sets current node pointer to point at its next node.
 * 					       If the next node is NULL or list's dummy node, current node
 * 					       is not incremented and False is returned.
 * 					       Otherwise, current node pointer is incremented and True returned
 ***************************************************************************************/
bool EdgeLinkedList::incrmntCurrNode() {

	if (m_currNode->m_nextListNode == m_tailDummy) { // reached list's end
		return false;
	}

	m_currNode = m_currNode->m_nextListNode; // has not reached end yet, move to next node
	return true;
}

/***************************************************************************************
 * function name: operator == (const EdgeLinkedList& listOperand)
 * The Input: Edge linked list to compare with
 * The output: True if all edges are equal, False if not
 * The Function operation: Compares each list's nodes. Method does not change the object
 ***************************************************************************************/
bool EdgeLinkedList::operator == (const EdgeLinkedList& listOperand) const {
	// scan both list and compare nodes
	ListNode* currOnObject = m_headDummy->m_nextListNode; // point to object's start
	ListNode* currOnOperand = listOperand.m_headDummy->m_nextListNode; // point to operand's start

	// scan until one of list's end is reached
	while (currOnObject != m_tailDummy && currOnOperand != listOperand.m_tailDummy) {
		if (currOnObject->m_edgeData != currOnOperand->m_edgeData) {
			return false; // mismatch found, return False
		}
		// move to next node on both lists
		currOnObject = currOnObject->m_nextListNode;
		currOnOperand = currOnOperand->m_nextListNode;
	}

	// done scanning and did not find mismatch, lists are equal only if both of them reached their end
	return currOnObject == m_tailDummy && currOnOperand == listOperand.m_tailDummy;
}
